<?php
/**
 * Dispatcher.php
 *
 * 分发器文件，定义分发器
 *
 * PHP Version 5.6
 *
 * @category PHP
 * @package  Dispatcher
 * @author   ctwj <908504609@qq.com>
 * @license  MIT https://github.com/ctwj/wechat_search/blob/master/LICENSE
 * @link     https://github.com/ctwj/wechat_search/
 * @date     2018-05-13 22:56:47
 * @modifyby ctwj
 */

namespace Telegram;

use Telegram\Object\Message;
use Telegram\Object\destination;
use Telegram\Dispatcher\DispatcherFactory;

/**
 * Dispatcher class
 *
 * 分发器类，暴露分发器接口
 *
 * @category PHP
 * @package  Dispatcher
 * @author   ctwj <908504609@qq.com>
 * @license  MIT https://github.com/ctwj/wechat_search/blob/master/LICENSE
 * @link     https://github.com/ctwj/wechat_search/
 */
class Dispatcher
{
    /**
     * 分发器实例对象
     *
     * @var [array] array of dispatcher instance
     */
    public $dispatcher;

    /**
     * 开始派发
     *
     * @return void
     */
    public function run()
    {
        $postNumber = getenv('POST_NUMBER_EACH_TIMES');
        if (intval($postNumber) <= 0) {
            $postNumber = 1;
        }
        $messages = $this->_getNeedPostMessages($postNumber);
        if (!count($messages)) {
            return;
        }
        $destinations = $this->_getDestination();
        if (!count($destinations)) {
            return;
        }

        $post_times = 0;
        foreach ($destinations as $des) {
            $disptcher = $this->_getInstance($des->type);
            $disptcher->loadconfig($des);
            try {
                $disptcher->dispatch($messages);
                $post_times += 1;

                // 消息设置为已推送
                getService('messageModel')->setMessagesPostSucc($messages);
            } catch (\Exception $e) {
                // 消息设置为推送失败
                getService('messageModel')->setMessagesPostFail($messages);
                getService('logger')->error('Dispather Fail', ['error' => $e->getMessage()]);
            }

            // 如果消息推送失败，那所有推送目的都会失败，因为当前都是telegram，所以直接退出循环
            // 后续如果推送目的地多样化，那这里不用break
            if (!$post_times) {
                break;
            }
        }
        // 更新推送次数
        if ($post_times) {
            $des->post_times += $post_times;
            getService('destinationModel')->updateDest($des);
        }
    }

    /**
     * 获取具体类型的采集器实例
     *
     * @param [string] $type 采集器类型
     *
     * @return void
     */
    private function _getInstance($type)
    {
        if (isset($this->dispatcher[$type])) {
            return $this->dispatcher[$type];
        }
        $this->dispatcher[$type] = DispatcherFactory::getInstance($type);
        return $this->dispatcher[$type];
    }

    /**
     * 获取需要推送的消息对象
     *
     * @param [integer] $name number
     *
     * @return array of Telegram\Object\Message
     */
    private function _getNeedPostMessages($number)
    {
        $data = getService('messageModel')->getUnPostMessages($number);
        if (empty($data)) {
            getService('logger')->info('Try Dispatcher Messages But No Message Need Dispatcher');
            return [];
        }
        return array_map(
            function ($item) {
                return new \Telegram\Object\Message($item);
            },
            $data
        );
    }

    /**
     * 获取需要分发的目的地
     *
     * @return array of Telegram\Object\destination
     */
    private function _getDestination()
    {
        $data = getService('destinationModel')->find('*', ['status' => true, 'ORDER' => ['id' => 'ASC']]);
        if (empty($data)) {
            getService('logger')->info('Try Dispatcher Messages But No Destination Found');
            return [];
        }
        return array_map(
            function ($item) {
                return new \Telegram\Object\Destination($item);
            },
            $data
        );
    }
}
